import sys
import os

file_path = os.path.abspath(__file__)
end = file_path.index('qmt_auto_trade') + 17
project_path = file_path[0:end]
sys.path.append(project_path)

import time
from datetime import datetime, timedelta

import mk_common.component.cache.cache_service as cache_service
import mk_common.component.common.common_service_fun_api as common_service_fun_api
import mk_common.component.qmt.qmt_real_time_api as qmt_real_time_api
import mk_common.util.data_frame_util as data_frame_util
import pandas as pd
from loguru import logger

import config.config_service as config_service
import push.push_msg_service as push_msg_service
import trade.trade_service as trade_service

CACHE_KEY = 'REAL_TIME_QUOTES'


# 读取excel数据
def read_excel_data():
    try:
        config_info_dict = config_service.get_config_info()
        strategy_template_path = config_info_dict.get('strategy_template_path')
        strategy_df = pd.read_excel(strategy_template_path, dtype=str)
        strategy_df = strategy_df.rename(columns={
            "ts_code": "symbol",
            "close": "buy_min_price",
        })
        # 遍历每一列
        for col in strategy_df.columns:
            # 检查列是否包含字符串类型的百分比
            if strategy_df[col].dtype == object and strategy_df[col].str.contains('%').any():
                # 移除%号并转换为浮点数，再除以100
                strategy_df[col] = strategy_df[col].str.rstrip('%').astype(float) / 100.0

        strategy_df = strategy_df[['symbol',
                                   'buy_min_price',
                                   'dominant_theme_count',
                                   'extra_col_16',
                                   'extra_col_17',
                                   'extra_col_18',
                                   ]]
        strategy_df['buy_min_price'] = strategy_df['buy_min_price'].astype(float)
        strategy_df['dominant_theme_count'] = strategy_df['dominant_theme_count'].astype(float)
        strategy_df['extra_col_16'] = strategy_df['extra_col_16'].astype(float)
        strategy_df['extra_col_17'] = strategy_df['extra_col_17'].astype(float)
        strategy_df['extra_col_18'] = strategy_df['extra_col_18'].astype(float)

        return strategy_df
    except BaseException as e:
        logger.error("读取策略文件异常:{}", str(e))
        title = "读取策略excel文件异常"
        msg = "读取策略excel文件异常,请检查文件时候存在或者打开,打开请关闭;或者文件列表名称是否修改"
        push_msg_service.push_msg(title, msg)

        return None


def strategy_run(test_flag):
    strategy_df = read_excel_data()
    if data_frame_util.is_empty(strategy_df):
        title = "读取策略excel文件为空"
        msg = "读取策略excel文件为空,请检查文件中是否存在数据"
        push_msg_service.push_msg(title, msg)
        return None
    else:
        strategy_choose(strategy_df, test_flag)


def strategy_choose(strategy_df, test_flag):
    strategy_df = common_service_fun_api.add_after_prefix(strategy_df)
    strategy_df = strategy_df.rename(columns={
        "symbol": "code"
    })

    symbol_list = list(strategy_df['symbol_prefix'])
    while True:
        now = datetime.now()
        now_hour = now.hour
        now_minute = now.minute

        # 上午收盘和下午收盘自动结束
        if bool(1-test_flag)  and ( (now_hour == 11 and now_minute >= 30) or (now_hour >= 15)):
            logger.info("收盘时间自动结束")
            break

        config_info_dict = config_service.get_config_info()
        # 上午结束时间
        am_end_time = config_info_dict.get('am_end_time')
        am_end_hour = int(am_end_time[0:2])
        am_end_minute = int(am_end_time[2:4])
        if  bool(1-test_flag)  and ((now_hour > am_end_hour) or (now_hour == am_end_hour and am_end_minute <= now_minute)):
            logger.info("策略配置结束时间到了")
            break
        # 下午结束时间
        pm_end_time = config_info_dict.get('pm_end_time')
        pm_end_hour = int(pm_end_time[0:2])
        pm_end_minute = int(pm_end_time[2:4])
        if  bool(1-test_flag)  and( (now_hour > pm_end_hour) or (now_hour == pm_end_hour and pm_end_minute <= now_minute)):
            logger.info("策略配置结束时间到了")
            break

        try:
            strategy_df_copy = strategy_df.copy()

            # 防止进入死循环
            time.sleep(0.3)
            empty_number = 0
            real_time_quotes_df = qmt_real_time_api.get_qmt_real_time_quotes(symbol_list)
            if data_frame_util.is_not_empty(real_time_quotes_df):
                set_cache(CACHE_KEY, real_time_quotes_df, test_flag)
            else:
                empty_number = empty_number + 1
                if empty_number % 50 == 1:
                    push_msg_service.push_msg("获取实时行情异常", '获取不到实时行情,请检查qmt是否登录运行成功')
                continue

            real_time_quotes_df = real_time_quotes_df.set_index(['symbol'], drop=False)
            strategy_df_copy = strategy_df_copy.set_index(['symbol_prefix'], drop=True)

            real_time_quotes_result_df = pd.merge(real_time_quotes_df, strategy_df_copy, how='outer',
                                                  left_index=True, right_index=True)

            real_time_quotes_result_df.dropna(subset=['symbol'], axis=0, inplace=True)

            # 买入条件check
            real_time_quotes_result_df = buy_condition_checker(real_time_quotes_result_df)
            if data_frame_util.is_empty(real_time_quotes_result_df):
                continue
            # 买入价格
            real_time_quotes_result_df = buy_price_checker(real_time_quotes_result_df)
            if data_frame_util.is_empty(real_time_quotes_result_df):
                continue
            # 涨速check
            choose_result_df = check_speed_up(real_time_quotes_result_df)

            if data_frame_util.is_empty(choose_result_df):
                continue
            else:
                strategy_buy(choose_result_df)

        except BaseException as e:
            title = "策略运行异常"
            msg = "策略运行异常,异常信息:" + str(e)
            push_msg_service.push_msg(title, msg)


# 策略运行
def strategy_buy(choose_result_df):
    for choose_one in choose_result_df.itertuples():
        symbol = choose_one.symbol
        try:
            last_price = choose_one.lastPrice
            trade_service.order_buy(symbol, last_price)
        except BaseException as e:
            title = "买入异常"
            msg = "买入股票异常,异常信息:" + symbol + "" + str(e)
            push_msg_service.push_msg(title, msg)


# 买入价格check
def buy_price_checker(real_time_quotes_result_df):
    return real_time_quotes_result_df.loc[
        real_time_quotes_result_df['lastPrice'] >= real_time_quotes_result_df['buy_min_price']]


# 买入条件check
def buy_condition_checker(real_time_quotes_result_df):
    config_info_dict = config_service.get_config_info()

    dominant_theme_count_min = config_info_dict.get('dominant_theme_count_min')
    dominant_theme_count_max = config_info_dict.get('dominant_theme_count_max')

    extra_col_16_min = config_info_dict.get('extra_col_16_min')
    extra_col_16_max = config_info_dict.get('extra_col_16_max')

    extra_col_17_min = config_info_dict.get('extra_col_17_min')
    extra_col_17_max = config_info_dict.get('extra_col_17_max')

    extra_col_18_min = config_info_dict.get('extra_col_18_min')
    extra_col_18_max = config_info_dict.get('extra_col_18_max')

    real_time_quotes_result_df = real_time_quotes_result_df.loc[
        (real_time_quotes_result_df['dominant_theme_count'] >= dominant_theme_count_min) & (
                real_time_quotes_result_df['dominant_theme_count'] <= dominant_theme_count_max)]
    if data_frame_util.is_empty(real_time_quotes_result_df):
        return None

    real_time_quotes_result_df = real_time_quotes_result_df.loc[
        (real_time_quotes_result_df['extra_col_16'] >= extra_col_16_min) & (
                real_time_quotes_result_df['extra_col_16'] <= extra_col_16_max)]
    if data_frame_util.is_empty(real_time_quotes_result_df):
        return None

    real_time_quotes_result_df = real_time_quotes_result_df.loc[
        ((real_time_quotes_result_df['extra_col_17'] >= extra_col_17_min) & (
                real_time_quotes_result_df['extra_col_17'] <= extra_col_17_max)) | (
                (real_time_quotes_result_df['extra_col_18'] >= extra_col_18_min) & (
                real_time_quotes_result_df['extra_col_18'] <= extra_col_18_max))]
    return real_time_quotes_result_df


# 涨速比较
def check_speed_up(real_time_quotes_break_up_df):
    one_df = real_time_quotes_break_up_df.iloc[0]
    now_time = one_df['timetag']
    compare_time_data_df = get_compare_time_data(now_time)
    choose_result_df = pd.DataFrame()
    if data_frame_util.is_empty(compare_time_data_df):
        return choose_result_df
    else:
        for stock_one in real_time_quotes_break_up_df.itertuples():
            symbol = stock_one.symbol
            try:
                last_price_now = stock_one.lastPrice
                compare_time_data_one_df = compare_time_data_df.loc[compare_time_data_df['symbol'] == symbol]
                if data_frame_util.is_empty(compare_time_data_one_df):
                    continue
                compare_time_data_one_df = compare_time_data_one_df.sort_values(by=['timetag'], ascending=False)
                last_price_compare = list(compare_time_data_one_df['lastPrice'])[0]
                if last_price_now > last_price_compare:
                    real_time_quotes_break_up_one_df = real_time_quotes_break_up_df.loc[
                        real_time_quotes_break_up_df['symbol'] == symbol]
                    choose_result_df = pd.concat([choose_result_df, real_time_quotes_break_up_one_df])
            except BaseException as e:
                logger.error("check涨速信息异常:{},{}", symbol, e)

    return choose_result_df


# 获取股票之前实时行情
def get_compare_time_data(now_time):
    result_df = cache_service.get_cache(CACHE_KEY)
    config_info_dict = config_service.get_config_info()
    strategy_interval_seconds = config_info_dict.get('strategy_interval_seconds')
    # 将字符串转换为 datetime 对象
    dt = datetime.strptime(now_time, "%Y%m%d %H:%M:%S")
    # 减去 间隔 秒
    new_dt = dt - timedelta(seconds=strategy_interval_seconds)
    # 将结果转换回字符串格式
    new_time_str = new_dt.strftime("%Y%m%d %H:%M:%S")
    result_df = result_df.loc[result_df['timetag'] <= new_time_str]
    return result_df


def set_cache(key, real_time_quotes_df, test_flag):
    real_time_quotes_df['timetag'] = real_time_quotes_df['timetag'].str[:17]

    realtime_quotes_now_one = real_time_quotes_df.iloc[0]
    time_tag = realtime_quotes_now_one['timetag']
    # 将字符串转换为 datetime 对象
    dt = datetime.strptime(time_tag, "%Y%m%d %H:%M:%S")

    # 减去 60 秒
    new_dt = dt - timedelta(seconds=60)

    # 将结果转换回字符串格式
    new_time_str = new_dt.strftime("%Y%m%d %H:%M:%S")
    result_df = cache_service.get_cache(CACHE_KEY)

    real_time_quotes_df['_id'] = real_time_quotes_df['timetag'] + "_" + real_time_quotes_df['symbol']
    if data_frame_util.is_empty(result_df):
        if test_flag:
            real_time_quotes_df['lastPrice'] = round(real_time_quotes_df['lastPrice'] - 0.01, 2)
            # 转换为 datetime 类型并减去 5 秒
            real_time_quotes_df['timetag'] = pd.to_datetime(real_time_quotes_df['timetag'],
                                                            format='%Y%m%d %H:%M:%S') - pd.Timedelta(seconds=5)
            real_time_quotes_df['timetag'] = real_time_quotes_df['timetag'].dt.strftime('%Y%m%d %H:%M:%S')
        result_df = real_time_quotes_df
    else:
        result_df = pd.concat([result_df, real_time_quotes_df])
    # 排除之前一分钟的数据
    result_df = result_df.loc[result_df['timetag'] >= new_time_str]
    result_df = result_df.drop_duplicates(['_id'])

    # 更新到缓存
    cache_service.set_cache(key, result_df)


if __name__ == '__main__':
    strategy_run(True)
